package handler

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"net/http"
	"sync"
	"time"

	"github.com/gorilla/websocket"
	"goserver/internal/model"
	"goserver/internal/service"
	"goserver/internal/metrics"
	"goserver/internal/alert"
)

var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true // 允许所有来源
	},
}

type WebSocketHandler struct {
	deviceService *service.DeviceService
	messageModel  *model.MessageModel
	connections   sync.Map // 存储所有websocket连接
}

func NewWebSocketHandler(deviceService *service.DeviceService, messageModel *model.MessageModel) *WebSocketHandler {
	return &WebSocketHandler{
		deviceService: deviceService,
		messageModel:  messageModel,
	}
}

func (h *WebSocketHandler) HandleWebSocket(w http.ResponseWriter, r *http.Request) {
	// 1. 获取并验证robotID
	robotID := r.URL.Query().Get("robotId")
	if robotID == "" {
		http.Error(w, "Missing robot ID", http.StatusBadRequest)
		return
	}

	// 2. 验证机器码
	config, err := h.deviceService.ValidateRobotID(r.Context(), robotID)
	if err != nil {
		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	// 3. 升级HTTP连接为WebSocket
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Printf("WebSocket upgrade failed: %v", err)
		return
	}

	// 4. 存储连接
	h.connections.Store(robotID, conn)
	defer func() {
		h.connections.Delete(robotID)
		conn.Close()
	}()

	// 5. 处理连接
	h.handleConnection(r.Context(), conn, robotID, config)
}

func (h *WebSocketHandler) handleConnection(ctx context.Context, conn *websocket.Conn, robotID string, config *service.RobotConfig) {
	// 更新在线设备数
	metrics.OnlineDevices.Inc()
	defer metrics.OnlineDevices.Dec()

	// 启动心跳
	go h.startHeartbeat(conn, robotID)

	// 设置读取超时
	conn.SetReadDeadline(time.Now().Add(60 * time.Second))

	for {
		// 1. 读取消息
		messageType, p, err := conn.ReadMessage()
		if err != nil {
			log.Printf("Read error: %v", err)
			metrics.MessageCounter.WithLabelValues("read", "error").Inc()
			alert.SendErrorAlert("WebSocket读取错误", fmt.Errorf("robotID: %s, error: %v", robotID, err))
			return
		}

		// 2. 重置读取超时
		conn.SetReadDeadline(time.Now().Add(60 * time.Second))

		// 3. 处理消息
		if messageType == websocket.TextMessage {
			start := time.Now()

			var msg model.Message
			if err := json.Unmarshal(p, &msg); err != nil {
				log.Printf("JSON decode error: %v", err)
				metrics.MessageCounter.WithLabelValues("decode", "error").Inc()
				continue
			}

			msg.RobotID = robotID
			
			// 4. 保存消息
			if err := h.messageModel.SaveMessage(ctx, &msg); err != nil {
				log.Printf("Save message error: %v", err)
				metrics.MessageCounter.WithLabelValues("save", "error").Inc()
				continue
			}

			// 记录消息处理延迟
			duration := time.Since(start).Seconds()
			metrics.MessageLatency.WithLabelValues("process").Observe(duration)
			metrics.MessageCounter.WithLabelValues("process", "success").Inc()

			// 5. 根据配置处理消息
			if config.QAType != 0 && config.CallbackURL != "" {
				go h.handleCallback(ctx, &msg, config)
			}
		}
	}
}

// 发送消息到客户端
func (h *WebSocketHandler) SendMessage(robotID string, msg *model.Message) error {
	conn, ok := h.connections.Load(robotID)
	if !ok {
		return errors.New("connection not found")
	}

	wsConn, ok := conn.(*websocket.Conn)
	if !ok {
		return errors.New("invalid connection type")
	}

	data, err := json.Marshal(msg)
	if err != nil {
		return err
	}

	return wsConn.WriteMessage(websocket.TextMessage, data)
}

// 回调处理
func (h *WebSocketHandler) handleCallback(ctx context.Context, msg *model.Message, config *service.RobotConfig) {
	// 1. 检查是否需要回调
	if !shouldCallback(msg, config) {
		return
	}

	// 2. 准备回调数据
	callbackData := map[string]interface{}{
		"robot_id": msg.RobotID,
		"type":     msg.SocketType,
		"messages": msg.List,
		"timestamp": time.Now().Unix(),
	}

	// 3. 转换为JSON
	jsonData, err := json.Marshal(callbackData)
	if err != nil {
		log.Printf("Callback data marshal error: %v", err)
		return
	}

	// 4. 发送回调请求
	client := &http.Client{
		Timeout: time.Second * 10,
	}

	req, err := http.NewRequestWithContext(ctx, "POST", config.CallbackURL, bytes.NewBuffer(jsonData))
	if err != nil {
		log.Printf("Create callback request error: %v", err)
		return
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-Robot-ID", msg.RobotID)

	resp, err := client.Do(req)
	if err != nil {
		log.Printf("Callback request error: %v", err)
		return
	}
	defer resp.Body.Close()

	// 5. 处理回调响应
	if resp.StatusCode != http.StatusOK {
		log.Printf("Callback failed with status: %d", resp.StatusCode)
		return
	}

	// 6. 解析响应
	var response struct {
		Code    int    `json:"code"`
		Message string `json:"message"`
		Data    string `json:"data"`
	}

	if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
		log.Printf("Callback response decode error: %v", err)
		return
	}

	// 7. 如果需要回复消息
	if response.Code == 200 && response.Data != "" {
		replyMsg := &model.Message{
			RobotID:    msg.RobotID,
			SocketType: 2, // 发送消息
			List: []model.MsgItem{
				{
					Type:    101, // 文本消息
					Content: response.Data,
				},
			},
		}

		if err := h.SendMessage(msg.RobotID, replyMsg); err != nil {
			log.Printf("Send reply message error: %v", err)
		}
	}
}

// 判断是否需要回调
func shouldCallback(msg *model.Message, config *service.RobotConfig) bool {
	// 如果未配置回调，直接返回false
	if config.QAType == 0 || config.CallbackURL == "" {
		return false
	}

	// 检查回复策略
	switch config.ReplyAll {
	case -1: // 只读消息不回调
		return false
	case 0: // 仅私聊和群聊@机器人回调
		for _, item := range msg.List {
			// 检查是否是私聊消息
			if item.RoomID == "" {
				return true
			}
			// 检查是否有@机器人
			for _, user := range item.AtUsers {
				if user == msg.RobotID {
					return true
				}
			}
		}
		return false
	case 1: // 私聊群聊全部回调
		return true
	default:
		return false
	}
}

// 添加心跳处理
func (h *WebSocketHandler) startHeartbeat(conn *websocket.Conn, robotID string) {
	ticker := time.NewTicker(30 * time.Second)
	defer ticker.Stop()

	for range ticker.C {
		if err := conn.WriteControl(websocket.PingMessage, nil, time.Now().Add(time.Second)); err != nil {
			log.Printf("Send ping to %s failed: %v", robotID, err)
			return
		}
	}
}
